#include <iostream>
#include <stdio.h>

/*
 * 多重继承没有覆盖的特点
 */

class Base1
{
	public:
		virtual void function_1()
		{
			printf("Base1 function_1...\n");
		}

		virtual void function_2()
		{
			printf("Base1 function_2...\n");
		}
};

class Base2
{
	public:
		virtual void function_3()
		{
			printf("Base2 function_3...\n");
		}

		virtual void function_4()
		{
			printf("Base2 function_4...\n");
		}
};


class Sub : public Base1, public Base2
{
	public:
		virtual void function_5()
		{
			printf("Sub function_5...\n");
		}

		virtual void function_6()
		{
			printf("Sub function_6...\n");
		}
};

int main(int argc, char ** argv)
{
	Sub sub;

	printf("size = %ld\n", sizeof(class Sub));	// 16。 直接继承两个父类，所以有两个虚函数表

	printf("sub address is %x.\n", (unsigned int)(long)&sub);	// this 指针，是堆栈里面的地址。
																// 虚表的地址不是this指针，是this指针的前8个字节。

	/* 对象的前8字节是第一个Base1的虚表 */
	printf("sub virtual table address is:%x\n", (unsigned int)*(long*)&sub);   		

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 4; i++) {
		long temp = *((long*)(*(long*)&sub) + i);	
		if (temp == 0) {
			printf("temp==0.\n");
			break;
		}

		pf = (pfunction)temp;
		pf();
	}

	/* 对象的第二个8字节是Base2的虚表 */
	printf("sub virtual table address is:%x\n", (unsigned int)*(long*)((long)&sub+8));  
	pfunction pf2;

	for (int k = 0; k < 2; k++) {
		long temp = *((long*)(*(long*)((long)&sub+8)) + k);
		pf2 = (pfunction)temp;
		pf2();
	}
}

/*
	sub address is bf989c30.
	sub virtual table address is:8048a48
	Base1 function_1...
	Base1 function_2...
	Sub function_5...
	Sub function_6...
	sub virtual table address is:8048a60
	Base2 function_3...
	Base2 function_4...  
 */

#if 0

1.类多一个直接继承父类，就多一个虚函数表。直接继承一个父类，一个虚函数表；直接继承两个父类，两个虚函数表；
2.间接继承不算。。
3.子类的虚函数放在第一个虚函数表。

int main(int argc, char ** argv)
{
    11c9:	f3 0f 1e fa          	endbr64 
    11cd:	55                   	push   %rbp
    11ce:	48 89 e5             	mov    %rsp,%rbp
    11d1:	48 83 ec 60          	sub    $0x60,%rsp
    11d5:	89 7d ac             	mov    %edi,-0x54(%rbp)
    11d8:	48 89 75 a0          	mov    %rsi,-0x60(%rbp)
    11dc:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
    11e3:	00 00 
    11e5:	48 89 45 f8          	mov    %rax,-0x8(%rbp)
    11e9:	31 c0                	xor    %eax,%eax
	Sub sub;
    11eb:	48 8d 05 06 2b 00 00 	lea    0x2b06(%rip),%rax        # 3cf8 <_ZTV3Sub+0x10>
    11f2:	48 89 45 e0          	mov    %rax,-0x20(%rbp)
    11f6:	48 8d 05 2b 2b 00 00 	lea    0x2b2b(%rip),%rax        # 3d28 <_ZTV3Sub+0x40>
    11fd:	48 89 45 e8          	mov    %rax,-0x18(%rbp)

	printf("size = %ld\n", sizeof(class Sub));	// 16。 直接继承两个父类，所以有两个虚函数表
    1201:	be 10 00 00 00       	mov    $0x10,%esi
    1206:	48 8d 3d 70 0e 00 00 	lea    0xe70(%rip),%rdi        # 207d <_ZStL19piecewise_construct+0x75>
    120d:	b8 00 00 00 00       	mov    $0x0,%eax
    1212:	e8 79 fe ff ff       	callq  1090 <printf@plt>

	printf("sub address is %x.\n", (unsigned int)(long)&sub);	// this 指针，是堆栈里面的地址。
    1217:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    121b:	89 c6                	mov    %eax,%esi
    121d:	48 8d 3d 65 0e 00 00 	lea    0xe65(%rip),%rdi        # 2089 <_ZStL19piecewise_construct+0x81>
    1224:	b8 00 00 00 00       	mov    $0x0,%eax
    1229:	e8 62 fe ff ff       	callq  1090 <printf@plt>
																// 虚表的地址不是this指针，是this指针的前8个字节。

	/* 对象的前8字节是第一个Base1的虚表 */
	printf("sub virtual table address is:%x\n", (unsigned int)*(long*)&sub);   		
    122e:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    1232:	48 8b 00             	mov    (%rax),%rax
    1235:	89 c6                	mov    %eax,%esi
    1237:	48 8d 3d 62 0e 00 00 	lea    0xe62(%rip),%rdi        # 20a0 <_ZStL19piecewise_construct+0x98>
    123e:	b8 00 00 00 00       	mov    $0x0,%eax
    1243:	e8 48 fe ff ff       	callq  1090 <printf@plt>

	typedef void(*pfunction)(void);
	
	pfunction pf;

	for (int i = 0; i < 4; i++) {
    1248:	c7 45 b8 00 00 00 00 	movl   $0x0,-0x48(%rbp)
    124f:	83 7d b8 03          	cmpl   $0x3,-0x48(%rbp)
    1253:	7f 3a                	jg     128f <main+0xc6>
		long temp = *((long*)(*(long*)&sub) + i);	
    1255:	8b 45 b8             	mov    -0x48(%rbp),%eax
    1258:	48 98                	cltq   
    125a:	48 8d 14 c5 00 00 00 	lea    0x0(,%rax,8),%rdx
    1261:	00 
    1262:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    1266:	48 8b 00             	mov    (%rax),%rax
    1269:	48 01 d0             	add    %rdx,%rax
    126c:	48 8b 00             	mov    (%rax),%rax
    126f:	48 89 45 c0          	mov    %rax,-0x40(%rbp)
		if (temp == 0) {
    1273:	48 83 7d c0 00       	cmpq   $0x0,-0x40(%rbp)
    1278:	74 14                	je     128e <main+0xc5>
			break;
		}

		pf = (pfunction)temp;
    127a:	48 8b 45 c0          	mov    -0x40(%rbp),%rax
    127e:	48 89 45 c8          	mov    %rax,-0x38(%rbp)
		pf();
    1282:	48 8b 45 c8          	mov    -0x38(%rbp),%rax
    1286:	ff d0                	callq  *%rax
	for (int i = 0; i < 4; i++) {
    1288:	83 45 b8 01          	addl   $0x1,-0x48(%rbp)
    128c:	eb c1                	jmp    124f <main+0x86>
			break;
    128e:	90                   	nop
	}

	/* 对象的第二个8字节是Base2的虚表 */
	printf("sub virtual table address is:%x\n", (unsigned int)*(long*)((long)&sub+8));  
    128f:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    1293:	48 83 c0 08          	add    $0x8,%rax
    1297:	48 8b 00             	mov    (%rax),%rax
    129a:	89 c6                	mov    %eax,%esi
    129c:	48 8d 3d fd 0d 00 00 	lea    0xdfd(%rip),%rdi        # 20a0 <_ZStL19piecewise_construct+0x98>
    12a3:	b8 00 00 00 00       	mov    $0x0,%eax
    12a8:	e8 e3 fd ff ff       	callq  1090 <printf@plt>
	pfunction pf2;

	for (int k = 0; k < 2; k++) {
    12ad:	c7 45 bc 00 00 00 00 	movl   $0x0,-0x44(%rbp)
    12b4:	83 7d bc 01          	cmpl   $0x1,-0x44(%rbp)
    12b8:	7f 36                	jg     12f0 <main+0x127>
		long temp = *((long*)(*(long*)((long)&sub+8)) + k);
    12ba:	8b 45 bc             	mov    -0x44(%rbp),%eax
    12bd:	48 98                	cltq   
    12bf:	48 8d 14 c5 00 00 00 	lea    0x0(,%rax,8),%rdx
    12c6:	00 
    12c7:	48 8d 45 e0          	lea    -0x20(%rbp),%rax
    12cb:	48 83 c0 08          	add    $0x8,%rax
    12cf:	48 8b 00             	mov    (%rax),%rax
    12d2:	48 01 d0             	add    %rdx,%rax
    12d5:	48 8b 00             	mov    (%rax),%rax
    12d8:	48 89 45 d0          	mov    %rax,-0x30(%rbp)
		pf2 = (pfunction)temp;
    12dc:	48 8b 45 d0          	mov    -0x30(%rbp),%rax
    12e0:	48 89 45 d8          	mov    %rax,-0x28(%rbp)
		pf2();
    12e4:	48 8b 45 d8          	mov    -0x28(%rbp),%rax
    12e8:	ff d0                	callq  *%rax
	for (int k = 0; k < 2; k++) {
    12ea:	83 45 bc 01          	addl   $0x1,-0x44(%rbp)
    12ee:	eb c4                	jmp    12b4 <main+0xeb>
	}
}
    12f0:	b8 00 00 00 00       	mov    $0x0,%eax
    12f5:	48 8b 4d f8          	mov    -0x8(%rbp),%rcx
    12f9:	64 48 33 0c 25 28 00 	xor    %fs:0x28,%rcx
    1300:	00 00 
    1302:	74 05                	je     1309 <main+0x140>
    1304:	e8 a7 fd ff ff       	callq  10b0 <__stack_chk_fail@plt>
    1309:	c9                   	leaveq 
    130a:	c3                   	retq

#endif
